package main

import "fmt"

type Book struct {
	title   string
	author  string
	subject string
	bookId  int
}

// Spec  如果结构体类型以大写字母开头，那么它是一个导出类型，可以从其他包访问它。
//  类似地，如果结构体的字段以大写开头，则可以从其他包访问它们/*
type Spec struct {
	Maker string
	model string
	Price int
}

/**
 * 结构体的嵌套
 */

type Human struct {
	name   string
	age    int
	weight int
}

type Address struct {
	city, state string
}

type Student struct {
	/* 匿名字段，那么默认Student就包含了Human的所有字段 */
	Human
	speciality string
	address    Address
}

type name struct {
	firstName string
	lastName  string
}

func main() {

	var book01 Book
	var book02 = Book{
		title:   "JAVA",
		author:  "john",
		subject: "thinking in java",
		bookId:  1000,
	}

	/* book01 描述 */
	book01.title = "Go 语言"
	book01.author = "www.runoob.com"
	book01.subject = "Go 语言教程"
	book01.bookId = 6495407

	/* 打印 Book01 信息 */
	fmt.Printf("Book 01 title : %s\n", book01.title)
	fmt.Printf("Book 01 author : %s\n", book01.author)
	fmt.Printf("Book 01 subject : %s\n", book01.subject)
	fmt.Printf("Book 01 book_id : %d\n", book01.bookId)

	fmt.Println("------------------------------------------")

	/* 打印 Book02 信息 */
	fmt.Printf("Book 02 title : %s\n", book02.title)
	fmt.Printf("Book 02 author : %s\n", book02.author)
	fmt.Printf("Book 02 subject : %s\n", book02.subject)
	fmt.Printf("Book 02 book_id : %d\n", book02.bookId)

	fmt.Println()

	// 结构体指针
	printBook01(&book01)

	fmt.Println("------------------------------------------")

	// 结构体嵌套
	mark := Student{Human{
		name:   "mark",
		age:    18,
		weight: 80,
	}, "Compute", Address{
		city:  "Chicago",
		state: "Illinois",
	}}

	/*
			在结构体中属于匿名结构体的字段称为提升字段，因为它们可以被访问，
		就好像它们属于拥有匿名结构字段的结构一样,例如Student对象中的Human，就是匿名对象
		在访问的时候，就可以通过student对象直接通过点访问。
	*/
	fmt.Println("His name is ", mark.name)
	fmt.Println("His age is ", mark.age)
	fmt.Println("His weight is ", mark.weight)
	fmt.Println("His speciality is ", mark.speciality)
	fmt.Println("His city is ", mark.address.city)
	fmt.Println("His state is ", mark.address.state)

	// 导出类型
	var spec Spec

	spec.Maker = "apple"
	spec.Price = 50000
	fmt.Println("Spec:", spec)

	/*结构体是值类型*/
	name01 := name{"Steve", "Jobs"}
	name02 := name{"Steve", "Jobs"}

	/*
	   结构体比较
	   结构体是值类型，如果每个字段具有可比性，则是可比较的。如果它们对应的字段相等，则认为两个结构体变量是相等的。
	*/
	if name01 == name02 {
		fmt.Println("name01 and name02 are equal")
	} else {
		fmt.Println("name01 and name02 are not equal")
	}

	name03 := name{firstName: "Steve", lastName: "Jobs"}
	name04 := name{}
	name04.firstName = "Steve"

	if name03 == name04 {
		fmt.Println("name03 and name04 are equal")
	} else {
		fmt.Println("name03 and name04 are not equal")
	}

	/*如果结构变量包含的字段是不可比较的，那么结构变量是不可比较的*/

	//image01 := image{data: map[int]int{
	//	0: 155,
	//}}
	//image02 := image{data: map[int]int{
	//	0: 155,
	//}}
	//
	//if image01 == image02 {
	//	fmt.Println("image01 and image02 are equal")
	//}

	/*结构体作为函数的参数*/

}

func printBook01(book *Book) {
	fmt.Printf("Book title : %s\n", book.title)
	fmt.Printf("Book author : %s\n", book.author)
	fmt.Printf("Book subject : %s\n", book.subject)
	fmt.Printf("Book book_id : %d\n", book.bookId)
}

func printBook02(book Book) {
	fmt.Printf("Book title : %s\n", book.title)
	fmt.Printf("Book author : %s\n", book.author)
	fmt.Printf("Book subject : %s\n", book.subject)
	fmt.Printf("Book book_id : %d\n", book.bookId)
}
